package com.googlecode.jtoy.productorandconsumer;

import java.util.LinkedList;

/**
 * wait()和notify()是根类Object的两个方法，也就意味着所有的JAVA类都会具有这个两个方法，为什么会被这样设计呢？
 * 我们可以认为所有的对象默认都具有一个锁，虽然我们看不到，也没有办法直接操作，但它是存在的。
 * wait()方法表示：当缓冲区已满或空时，生产者或消费者线程停止自己的执行，放弃锁，使自己处于等待状态，让另一个线程开始执行；
 * notify()方法表示：当生产者或消费者对缓冲区放入或取出一个产品时，向另一个线程发出可执行通知，同时放弃锁，使自己处于等待状态。
 * 
 * @author shangxj
 * @date 4:25:20 PM, Aug 31, 2011
 */
public class WaitAndNotify {

	private LinkedList<String> myList = new LinkedList<String>();
	private int MAX = 100;
	private int i = 0;

	public static void main(String[] args) {
		new WaitAndNotify().start();
	}

	public void start() {
		new Productor().start();
		new Consumer().start();
		new Consumer().start();
	}

	class Productor extends Thread {

		public void run() {
			while (true) {

				try {
					Thread.sleep((long) (100 * Math.random()));
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}

				synchronized (myList) {
					try {
						while (myList.size() == MAX) {
							System.out.println("warning: it's full!");
							myList.wait();
						}
						String product = String.valueOf(++i);
						if (myList.add(product)) {
							System.out.println("Productor: ++++++++++++++++++++" + product);
							myList.notify();
						}
					} catch (InterruptedException e) {
						System.out.println("productor is interrupted!");
					}
				}
			}
		}
	}

	class Consumer extends Thread {

		public void run() {
			while (true) {
				try {
					Thread.sleep((long) (200 * Math.random()));
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}

				synchronized (myList) {
					try {
						while (myList.size() == 0) {
							System.out.println("warning: it's empty!");
							myList.wait();
						}
						String product = myList.removeFirst();
						System.out.println("Consumer: --------------------" + product);
						myList.notify();
					} catch (InterruptedException e) {
						System.out.println("consumer is interrupted!");
					}
				}
			}
		}
	}

}